
__author__="Action Farsi"
__date__ ="$21-giu-2009 12.10.01$"

from logger import logging
from random import randint, choice
import random as rnd
import libtcodpy as lt
import itertools
import globals


from utilities import *

MIN_SIZE = (100,100)
TRIG = [vector([1,0]),vector([0,1]),
       vector([-1,0]),vector([0,-1])]


from entity import *



tiles = {}
	
class Tile:
	def __init__(self, name,
					   symb = '.', bg = lt.black, fg = lt.light_grey,
					   is_pss = True, is_out = True, is_water = False):
		self.name = name
		self.description = "a bit of ground"
		self.is_pss = is_pss
		self.is_water = is_water
		self.is_out = is_out
		self.bg = bg
		self.fg = fg
		self.symb = symb
        

		
		globals.tiles[name] = self

Tile('wall', '#', lt.dark_grey, lt.light_grey, False, False, False)
Tile('impenetrable wall', '%', lt.dark_grey, lt.light_grey, False, False, False)
Tile('concrete', ' ', lt.dark_grey, lt.light_grey, True, False, False)
Tile('wooden plank', ' ', lt.Color(35,60,34), lt.light_grey, True, True, False)
Tile('grass', '.', lt.Color(70,180,40), lt.light_grey, True, True, False)
Tile('floor', ' ', lt.Color(35,60,34), lt.light_grey, True, False, False)
Tile('sea', ' ', lt.blue, lt.light_grey, False, True, True)
		
class Map():
    def __init__(self,size):
        tile_def = 'impenetrable wall'
        self.map = matrix(*size, init = tile_def)
        self.tmap = matrix(*size, init = False)

        self.size = size
        self.entrypoint = []

        self.entities = []

    def __iter__(self):
        for i,j in xyiter(self.size):
                yield self.map[j][i],(i,j)

    def __getitem__(self,key):
        try:
        ## TODO get slice and set slice
            if len(key) == 2:
                return self.map[key[1]][key[0]]
        except IndexError:
            return None


    def __setitem__(self,key, value):
        try:
            if isinstance(key[0],slice):
                xr = xrange(key[0].start or 0, key[0].stop+1, key[0].step or 1)
            else:
                xr = [key[0]]
            if isinstance(key[1],slice):
                yr = xrange(key[1].start or 0, key[1].stop+1, key[1].step or 1)
            else:
                yr = [key[1]]
            for j in yr:
                for i in xr:
                    # TODO procedure for tile, not just character
                    self.map[j][i] = value[:]
                    # TODO set also TMAP dependin
                    if value[:] == " ":
                        self.tmap[j][i] = True
        #   self.map[key[1]],[key[0]] = value
        except IndexError:
            pass

    def __len__(self):
        return self.size[0] * self.size[1]

    def iter(self):
        return itertools.product(xrange(self.size[0]), xrange(self.size[1]))

    def is_inside(self,pos):
        return not (pos[0] > 0 and pos[0] <= self.size[0] and pos[1] > 0 and pos[1] <= self.size[1])

    ## Should not have entities, only tiles
    def get_entity(self,pos, near = 0, filtr = Entity, exclude = None):
        ent_here = [ e for e in self.entities \
                    if ((e.pos[0] - pos[0])**2 + (e.pos[1] - pos[1])**2 <= near ) \
                    and (isinstance(e,filtr)) and (e is not exclude) ]
        return ent_here

    def remove_ent(self, ent):
        self.entities.remove(ent)
        ent.owner == None

    def add_ent(self, ent, random_pos = None, pos = None):
        self.entities.append(ent)
        if random_pos:
            while True:
                pos = [ rnd.randrange(x) for x in self.size ]
                if self.is_free(pos):
                    break
            ent.pos = pos
        if pos:
            ent.pos = pos
        ent.owner = self

    def is_free(self, pos):
        return  (self.is_walkable(pos)) # (not self.get_entity(pos, filtr = Actor)) and

    def is_walkable(self,pos):
        if self.is_in(pos):
            return False
        return self.tmap[pos[1]][pos[0]]

    def is_in(self,pos):
        return pos[0] <= 0 or pos[0] >= self.size[0] \
            or pos[1] <= 0 or pos[1] >= self.size[1]
        
    # Drawing function
    def draw_rect(self, pos1, pos2, fill = False, tile = "#"):
        x1,y1 = pos1
        x2,y2 = pos2

        if fill:
            self[x1:x2,y1:y2] = tile
        else:
            self[x1:x2,y1] = tile
            self[x1,y1:y2] = tile
            self[x2,y1:y2] = tile
            self[x1:x2,y2] = tile

    def blit(self, pos, map, rotate = 0):
        """ If % skip """
        dx, dy =  ((0,0,map.size[0]-1,map.size[1]-1),
                  (0,map.size[0]-1,map.size[0]-1,0))
        cs,sn = TRIG[rotate]
        dx,dy = dx[rotate],dy[rotate]

        for x,y in xyiter(map.size):
            if map[x,y] == '%':
                continue
            self[x*cs + y *sn + pos[0] +dx,
            -x*sn + y*cs + pos[1] + dy] = map[x,y]

    
    def is_passage(map,pos):
        return (map.is_walkable(pos+vector((-1,0))) and map.is_walkable(pos+(1,0) ) ) or \
               (map.is_walkable(pos+vector((0,-1))) and map.is_walkable(pos+(0,1) ) )

    def count_neigh(map,pos,tile = ' '):
        neigh = []
        if map[pos+(1,0)]==tile: neigh.append('E')
        if map[pos+(-1,0)]==tile: neigh.append('W')
        if map[pos+(0,1)]==tile: neigh.append('N')
        if map[pos+(0,-1)]==tile: neigh.append('S')
        return neigh

def rotate2(map, angle):
    """ 1 = 90, 2 = 180, 3 = 270 """
    w,h = map.size

    if angle == 1:
        nm = Map((h,w))
        for x,y in xyiter((w,h)):
                nm[y, h-x-1] = map[x,y]
    if angle == 2:
        nm = Map((w,h))
        for x,y in xyiter((w,h)):
                nm[w-y, h-x] = map[x,y]
    if angle == 3:
        nm = Map((h,w))
        for x,y in xyiter((w,h)):
                nm[w-y, x] = map[x,y]

    return nm

def matrix(w,h, init = ""):
    if hasattr(init,"__call__"):
        return [[init((x,y)) for x in xrange(w) ] for y in xrange(h)]
    return [[init for x in xrange(w) ] for y in xrange(h)]

def rotate(mat, angle):
    """ 1 = 90, 2 = 180, 3 = 270 """
    w,h = len(mat),len(mat[0])
    if angle == 0:
        return mat

    if angle == 1:
        nm = matrix(h,w)
        for x,y in xyiter((w,h)):
                nm[y][h-x-1] = mat[x][y]
    if angle == 2:
        nm = matrix(w,h)
        for x,y in xyiter((w,h)):
                nm[w-y-1][h-x-1] = mat[x][y]
    if angle == 3:
        nm = matrix(h,w)
        for x,y in xyiter((w,h)):
                nm[w-y-1][x] = mat[x][y]

    return nm

def check_border(l1,l2):
    print l1, l2
    connect = False
    connectable = False
    sim = 0
    for a,b in zip(l1,l2):
        if a == b:
            sim += 1
            if a == ' ':
                connect = True
    return connect
                
         

## Post Processing
def flood(map,start):
    ## TODO generic flood rule
    neighbours = [(1,0),(-1,0),(0,1),(0,-1)]

    ## Init Flood map
    flood_map = matrix(*map.size, init = lambda p : 0 if map.is_walkable(p) else -1)
    print False and 0 or -1
    #flood_map[start[1]][start[0]] = 1

    ## recursive flooding
    def flooding(p):
        flood_map[p[1]][p[0]] = 1
        for n in neighbours:
            try:
                if flood_map[(p+n)[1]][(p+n)[0]] == 0:
                    flooding(p + n)
            except IndexError:
                pass

    flooding(start)

    return flood_map



curr_tile = ' '
curr_mode = "SET"
#map = []

def set_tile(tile):
    global curr_tile
    curr_tile = tile

def put_tile(x, y):
    if not the_map.is_inside((x,y)):
        return True
    if curr_mode is "SET":
        the_map[x,y] = curr_tile[:]
    if curr_mode is "UNION":
        if not the_map[x,y] == ' ':
            the_map[x,y] = curr_tile[:]
    return True

# Helper coord function
# TODO use vector class
def add_v(*vect):
    return [sum(i) for i in itertools.izip(*vect)]

# Helper inclusion check
def is_in_delta(p,a,b):
    for i,x in enumerate(p):
        if a[i] > x:
            return False
        if b[i] < x:
            return False
    return True

# Helper rectangle
def draw_rect(pos1, pos2, fill = False, tile = "#", grid = None):
    x1,y1 = pos1
    x2,y2 = pos2

    if not grid:
        grid = the_map

    if fill:
        grid[x1:x2,y1:y2] = tile
    else:
        grid[x1:x2,y1] = tile
        grid[x1,y1:y2] = tile
        grid[x2,y1:y2] = tile
        grid[x1:x2,y2] = tile

#

class MFeat:
    """Base class for map feature.

    Every room has a symbolic representation (generate) and an effective tilation (draw)

    The room has also a series of meta-data like entrypoints (to connect to other rooms)
    and scriptspoints, that will be associated with script event.

    """
    def __init__(self, pos, size):
        self.pos = pos
        self.size = size
        self.tiles = { 'floor': ' ',
                        'wall': '#',
                        'door': '+'}
        self.entry_pts = []
        self.scr_pts = [vector((1,1))]  #Feats should always have at least one script-point
        

        self.sketch = Map(self.size)
        self.map_f = matrix(*self.size)

    def draw(self, canvas = None):
        sketch = Map(self.size)

        if canvas:
            canvas.blit(self.pos, sketch, self.angle)

        return sketch

    def is_in(self,pos):
        ## TODO use floodfilled map
        return is_in_delta(pos, self.pos, self.pos + self.size)
        
    def get_border(self,side):
        if side in ['N','n',0]:
            return self.sketch[:,0]
        if side in ['W','w',1]:
            return self.sketch[0,:]
        if side in ['S','s',2]:
            return self.sketch[:,-1]
        if side in ['E','e',3]:
            return self.sketch[-1,:]
            
    def flood():
        for p in xyiter(self.size):
            if self.sketch.is_walkable(p):
                self.map_f[p[0]][p[1]] = -1
            else:
                self.map_f[p[0]][p[1]] =  0
        
            
        

class MTile(MFeat):
    def __init__(self, pos, tile, angle = 0):
        MFeat.__init__(self, pos, (len(tile),len(tile[0])))
        self.scr_pt = []
        self.entry_pts = []

        tile = rotate(tile,angle)

        for x in xrange(len(tile)):
            for y in xrange(len(tile[0])):
                t = tile[x][y]
                if t in ['E','/',' ']:
                    self.sketch[x,y] =  self.tiles['floor']
                    continue
                if t == '*':
                    self.entry_pts.append((x,y))
                    self.sketch[x,y] = self.tiles['wall']
                if t == '@':
                    self.scr_pts.append((x,y))
                    self.sketch[x,y] = self.tiles['floor']
                if t == '#':
                    self.sketch[x,y] = self.tiles['wall']

class BareRoom(MFeat):
    def __init__(self, pos, size):
        MFeat.__init__(self,pos,size)

        self.sketch.draw_rect((0,0),vector(self.size) - (1,1),tile = '#')
        self.sketch.draw_rect((1,1),vector(self.size) - (2,2), tile = ' ', fill = True)
                
class Room(MFeat):
    """Base class for constructing rooms.

    Every room has a symbolic representation (generate) and an effective tilation (draw)

    The room has also a series of meta-data like entrypoints (to connect to other rooms)
    and scriptspoints, that will be associated with script event.

    """
    def __init__(self, pos, size):
        MFeat.__init__(self,pos,size)
        self.generate()

    def generate(self):
        "The room is generated overlapping 2 rectangles"
        w,h = self.size
        self.angle = 0
        #self.angle = rnd.randint(0, 3)

        #self.layout = [[" " for col in xrange(w) ] for row in xrange(h)]
        self.p = [vector([0,0]),[],[],self.size - vector([1,1])]

        # Choose 4 points and order them for having tho overlapping rooms
        self.p[1] = vector((rnd.randrange(0+3,w-2),rnd.randrange(0+3,h-2)))
        self.p[2] = vector((rnd.randrange(0,self.p[1][0]-2),rnd.randrange(0,self.p[1][1]-2)))

        #choose entrypoints
        # TODO randomize more
        self.entry_pnts = [vector([0,
                                 rnd.randrange(0 + 1, self.p[1][1]-1)]),
                           vector([rnd.randrange(self.p[2][0]+1, w-1), h-1
                            ])]

        self.schematic
        # TODO floodfill on occupation map
        
    def draw(self, canvas = None):
        sketch = Map(self.size)

        logging.debug("Draw room %s,%s,%s,%s"%(self.p[0],self.p[1],self.p[2],self.p[3]))
        sketch.draw_rect(self.p[0],self.p[1],tile = self.tiles['wall'])
        sketch.draw_rect(self.p[2],self.p[3],tile = self.tiles['wall'])
        sketch.draw_rect(add_v(self.p[0], (1,1) ),add_v(self.p[1], (-1,-1) ),tile = self.tiles['floor'], fill = True)
        sketch.draw_rect(add_v(self.p[2], (1,1) ),add_v(self.p[3], (-1,-1) ),tile = self.tiles['floor'], fill = True)

        for door in self.entry_pnts:
            sketch[door] = self.tiles['door']

        if canvas:
            canvas.blit(self.pos, sketch, self.angle)

        return sketch

    def draw_doors(self, canvas = None):
        sketch = Map(self.size)
        for door in self.entry_pnts:
            sketch[door] = self.tiles['door']

        if canvas:
            canvas.blit(self.pos, sketch, self.angle)

        return sketch

    def get_extrema(self):
        ## TODO use floodfilled map
        dx,dy =  ((0,0,self.size[0]-1,self.size[1]-1),
                  (0,self.size[0]-1,self.size[0]-1,0))
        delta = vector((dx[self.angle],dy[self.angle]))
        return self.size * TRIG[self.angle] + delta

def gen_building():
    """
     Put first room with doors (one is exit level)
     for each door:
        create a room, share the door and one wall
    """
    logging.debug("Generating building")
    size = (51,51)
    s_map = Map(size)
    my_bsp = lt.bsp_new_with_size(0,0,50,50)
    lt.bsp_split_recursive(my_bsp,0,4,7,7,1.7,1.7)

    rooms = []

    def draw_room(node, userData) :
        if (lt.bsp_is_leaf(node)):
            r = BareRoom(vector([node.x,node.y]),vector([node.w+1,node.h+1]))
            rooms.append(r)
            node.room = r
            s_map.blit(r.pos,r.sketch)
        return True

    lt.bsp_traverse_post_order(my_bsp,draw_room)

    ## Connect rooms
    for i in xrange(100):
        # Choose random point
        p = vector((rnd.randrange(1,size[0]-1),rnd.randrange(1,size[1]-1)))
        s = vector((rnd.randrange(4,11),rnd.randrange(4,11)))

        #Check it's on a wall
        if not s_map[p] =='#': continue
        if not s_map.is_passage(p): continue
        for r in rooms:
            if r.is_in(p):
                r.entry_pnts.append(r.pos - p - (1,1))
                r.sketch[r.pos-p - (1,1)] = '/'
        #s_map[p] = '/'


    # Entrance room
    #rooms.append(Room(vector([25,25]),vector([7,7])))

    # Choose one door
    #rooms[-1].entry_pnts[0]
        

    # Draw rooms
    for r in rooms:
        s_map.blit(r.pos,r.sketch)
        s_map[r.pos + r.script_pnts[0]] = 'o'

#    # Delete disconected doors
#    for r in rooms:
#        for d in r.entry_pnts:
#            if not the_map.is_passage(r.pos + d):
#                r.entry_pnts.remove(d)
    # redraw
#    for r in rooms:
#        r.draw(the_map)
#        the_map[r.pos + r.script_pnts[0]] = 'o'

#    for r in rooms:
#        r.draw_doors(the_map)

    s_map.rooms = rooms
    return s_map

class Level():
    """ Contains the map, the entity list, the quest objects
    """
    def __init__(self):
        ## BOL list
        self.BOL = {}
        self.ents = []
        self.scr_pts = []
        self.entry_pts = []

    def get_entity(self,pos, near = 0, filtr = Entity, exclude = None):
        ent_here = [ e for e in self.ents \
                    if ((e.pos[0] - pos[0])**2 + (e.pos[1] - pos[1])**2 <= near ) \
                    and (isinstance(e,filtr)) and (e is not exclude) ]
        return ent_here

    def remove_ent(self, ent):
        self.ents.remove(ent)
        ent.owner = None

    def add_to_list(self, ent):
        self.BOL[ent.ID] = ent
        if 'inventory' in ent.__dict__:
            for e in ent.inventory:
                self.add_to_list(e)
                logging.debug('Added to big list '+ str(e))

    def add_ent(self, ent, random_pos = None, pos = None):
        ## Add entity and recursively inventory to the BOL
        self.add_to_list(ent)
        self.ents.append(ent)
        if random_pos:
            while True:
                pos = [ rnd.randrange(x) for x in self.map.size ]
                if self.is_free(pos):
                    break
            ent.pos = pos
        elif pos is not None:
            ent.pos = pos
        ent.owner = self
    
    def is_free(self, pos):
        return (self.is_walkable(pos)) and (not self.get_entity(pos, filtr = Entity))

    def is_walkable(self,pos):
        return lt.map_is_walkable(self.tmap,pos[0],pos[1])

    def update_walkability(self, complete = False):
        lt.map_clear(self.tmap)
        for i in self.map:
            lt.map_set_properties(self.tmap,i[1][0],i[1][1],
                                  globals.tiles[i[0]].is_pss,globals.tiles[i[0]].is_pss)
        for e in [e for e in self.ents if isinstance(e,Object)]:
            if not e.is_passable:
                lt.map_set_properties(self.tmap, e.pos[0], e.pos[1],False,False)

def generate_outdoor():
    #Generate
    pass

def generate_level(seed = "af"):
    rnd.seed(seed)

    global the_map
    global the_level

    #poz = [(0,0),(0,20),(20,0),(20,20),(0,40),(40,0),(40,20),(20,40),(40,40)]
    poz = [(a*20,b*20) for a,b in xyiter([3,3])]
    
    rooms = []
    for p in poz:
        rooms.append(MTile(p, choice(feat_tiles), randint(0,3)))
    
    a = rooms[0].get_border('E')
    b = rooms[poz.index((20,0))].get_border('W')
    
    map_conn = matrix([120,120], 0)
    for x,y in xyiter( [0,60]):
        map_conn[y*2+1][x*2+1] = -1
    
    
    print check_border(a,b)
    
    the_map = Map([60,60])
    the_map.rooms = rooms

    for f in rooms:
        the_map.blit(f.pos,f.sketch)

    the_level = Level()

    l = the_level
    l.map = the_map
    

    scr_pts()

    

     ## Update walkabilty map
    l.tmap = lt.map_new(60,60)
    l.update_walkability()
    return l

def scr_pts():
    l = the_level
    for r in the_level.map.rooms:
        l.scr_pts.extend(r.scr_pts)



def generate_arena(w,h):
    global the_map
    logging.debug("Generating arena")

    the_map = Map((w,h))
    # Border of the map
    #the_map.draw_rect((1,1),(w-2,h-2),tile =' ', fill=True)
    
    #draw_rect((15,15),(20,20),fill = True)

    rooms = []#Room(vector([11,11]),vector([10,10]))]
    macro_size = vector((11,11))
    macro_grid = [vector((1,1)),vector((0,3)),vector((3,2))]

#    #Draw room
#    for i in macro_grid:
#        #p = vector((rnd.randrange(0+3,w-2),rnd.randrange(0+3,h-2)))
#        new_room = Room(i*macro_size+vector((1,1)),macro_size)
#        rooms.append(new_room)
#
#    for r in rooms:
#        r.draw()
    
    lt.line(13,11,10,17, put_tile)
    the_map[10:30,5:7] = '#'

    the_map[2,0] = '>'

    return the_map

def gen_dungeon():
    _NTRY = 1000
    sx,sy = (60,60)
    s_map = Map((sx,sy))

    feats = [BareRoom(((sx-6)/2,(sy-6)/2),(6,6))]
    s_map.blit(feats[0].pos,feats[0].sketch)

    for i in xrange(_NTRY):
        # Choose random point
        p = vector((rnd.randrange(1,sx-1),rnd.randrange(1,sy-1)))
        s = vector((rnd.randrange(4,11),rnd.randrange(4,11)))
        feat = BareRoom(p,s)

        #Check it's on a wall
        if not s_map[p]=='#': continue

        #Find out the direction
        neigh = s_map.count_neigh(p)
        if 'N' in neigh:
            p = p - (0,s[1]-1)
        if 'E' in neigh:
            p = p - (s[0]-1,0)
        
        is_free = True

        #try to fit the room
        for x,y in feat.sketch.iter():
            if s_map[p+[x,y]] not in ('%','#'):
                is_free = False
                break

        if not is_free: continue

        #Draw sketch and add feature to the list
        feat.pos = p
        s_map.blit(p,feat.sketch)
        feats.append(feat)

    return s_map


def test_map(level):
    print "Map test"
    logging.debug("Testing map")
    ## Initializations
    ORIGIN = (1,1, 100, 80)

    lt.console_init_root(ORIGIN[2], ORIGIN[3], 'AfW',False)
    finish_loop = False
    
    map = level.map
    
    map_f = flood(level.map,(5,5))
    show_flood = False
    #libtcod.console_set_keyboard_repeat(10, 10)


    #map = method()#60,60
    ## Main Loop ##
    while (not lt.console_is_window_closed() and not finish_loop):
        lt.console_set_background_color(None,lt.black)
        lt.console_set_foreground_color(0,lt.black)
        lt.console_clear(None)

        ## Rendering
        for j in xrange(min(map.size[1], ORIGIN[3]-ORIGIN[1])):
            for i in xrange(min(map.size[0], ORIGIN[2]-ORIGIN[0])):
                
                lt.console_set_back(None, i+ORIGIN[0], j+ORIGIN[1], lt.grey, lt.BKGND_SET)
                lt.console_put_char(None, i+ORIGIN[0], j+ORIGIN[1], map[i,j], lt.BKGND_NONE)
                if show_flood:
                    if map_f[j][i] == 1:
                        lt.console_set_fore(0, i+ORIGIN[0], j+ORIGIN[1], lt.red)
                        lt.console_set_char(None, i+ORIGIN[0], j+ORIGIN[1], '*')
                   

        lt.console_flush()
        key = lt.console_check_for_keypress()
        if key.vk == lt.KEY_ESCAPE:
            finish_loop = True
        if key.vk == lt.KEY_ENTER:
            map = method()
        if key.c == ord('f'):
            show_flood = not show_flood

        mouse_st = lt.mouse_get_status()
        if mouse_st.lbutton_pressed:
            ## TODO
            ## Mouse position depends on center of the screen
            mouse_pos = vector((mouse_st.cx-ORIGIN[0],mouse_st.cy-ORIGIN[1]))
            map_f = flood(level.map,mouse_pos)
            show_flood = True
            #print map.is_passage(mouse_pos)
            
#        for i,r in enumerate(map.rooms):
#            if r.is_in((mouse_st.cx,mouse_st.cy)):
#                r.tiles['floor']='.'
#                r.draw(map)
#                print i
    
## Algorithm for creating level
## 1) Level graph (easiest entry -.exit)
##   - Choose level type
##   - ITerate over graph for complexity
##   - Set puzzle structure (enumerate the graph)
## 2) Create abstract map from graph
##   - Each graph node a map-feature (room, building)
##   - Positioning not overlapping of feature
## 3) Carve rough sketch and add connection (s_map + connection_map)
## 3) Use abstract map do add flavors (f_map) & room entities
## 4) Create walkable map

def level_generator():
    the_level = Level()

    #Feature list
    feats = []

    #Sketch_map
    s_map = Map((50,50))

    return the_level

def load_level(file = 'map.bmp'):
    ## Handlers
    def tile(x,y,t):
        return True
        
    def ent(x,y,t):
        if t == 'E':
            the_level.scr_pts.append((x,y))
        if t == '@':
            the_level.entry_pts.append((x,y))
        if t == '/':
            the_level.add_ent(Door(), pos = (x,y))
        return False
        

    ## TODO Level info in sep file
    ## Containing enemys and plot info
    color_map = { (255,255,255): (tile,'concrete'),
                  (0,0,0)      : (tile,'wall'),
                  (0,0,255):     (ent,'@'),
                  (255,0,0):     (ent,'E'),
                  (0,255,0):     (ent,'*'),
                  (185,122,87):  (ent,'/'),
                  (120,120,120): (tile,'impenetrable wall'),}
    
    ## Create a level    
    the_level = Level()
    
    ## Create the map
    
    #  load file bpm
    im = lt.image_load(file)
    w,h = lt.image_get_size(im)
    
    # Create empty map
    the_map = Map((w,h))

    for x in xrange(w):
        for y in xrange(h):
            col = lt.image_get_pixel(im,x,y)
            c = color_map[ (col.r,col.g,col.b)]
            if c[0](x,y,c[1]):
                the_map[x,y] = c[1]
            else:
                the_map[x,y] = 'concrete'
            
    the_level.map = the_map
    ## Update walkabilty map
    the_level.tmap = lt.map_new(w,h)
    the_level.update_walkability()
    
    return the_level

feat_tiles = []

def load_tiles(file = "tiles/building.bmp"):
    tile = None
    ent = None
    ## TODO Level info in sep file
    ## Containing enemys and plot info
    color_map = { (255,255,255): (tile,'concrete'),
                  (0,0,0)      : (tile,'wall'),
                  (0,0,255):     (ent,'@'),
                  (255,0,0):     (ent,'E'),
                  (0,255,0):     (ent,'*'),
                  (185,122,87):  (ent,'/'),
                  (120,120,120): (tile,'impenetrable wall'),}

    ## Create the map

    #  load file bpm
    im = lt.image_load(file)
    w,h = lt.image_get_size(im)

    size = 20


    for i in [0,1,2,3,4]:
        for j in [0,1,2,3]:
            tile =  [[" " for col in xrange(size) ] for row in xrange(size)]
            for x in xrange(size):
                for y in xrange(size):
                    col = lt.image_get_pixel(im,x+i*size,y+j*size)
                    c = color_map[ (col.r,col.g,col.b) ]
                    tile[x][y] = c[1]
            feat_tiles.append(tile)

#load_tiles()
load_tiles("tiles/map.bmp")



if __name__ == "__main__":
    test_map(generate_level())
    #test_map(load_level())
    pass